﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace DistributedClient
{
    public class BroadcastReceivedEventArgs : EventArgs
    {
        private IPEndPoint endPoint;

        public BroadcastReceivedEventArgs(IPEndPoint ep)
        {
            endPoint = ep;
        }

        public IPEndPoint EndPoint { get { return endPoint; } }
    }

    public delegate void BroadcastReceivedEventHandler(object sender, BroadcastReceivedEventArgs e);

    public class BroadcastListener
    {
        private UdpClient client;
        private IPEndPoint endpoint;
        private Thread listener;
        private bool stop;

        public event BroadcastReceivedEventHandler BroadcastReceived;

        public BroadcastListener(int p)
        {
            endpoint = new IPEndPoint(IPAddress.Any, p);
            client = new UdpClient(endpoint);
            client.AllowNatTraversal(true);
            client.Client.ReceiveTimeout = 50;
            listener = new Thread(listen);
        }

        public void Start()
        {
            Console.WriteLine("Listening for broadcasts on port {0}", endpoint.Port);
            stop = false;
            listener.Start();
        }

        public void Stop()
        {
            stop = true;
        }

        protected virtual void OnBroadcastReceived(BroadcastReceivedEventArgs e)
        {
            BroadcastReceivedEventHandler handler = BroadcastReceived;
            if (handler != null) { handler(this, e); }
        }

        private void listen()
        {
            while (!stop)
            {
                try
                {
                    IPEndPoint ep = null;
                    byte[] message = client.Receive(ref ep);

                    if (Encoding.ASCII.GetString(message) == "TracedReality Broadcast")
                    {
                        BroadcastReceivedEventArgs e = new BroadcastReceivedEventArgs(ep);
                        OnBroadcastReceived(e);
                    }
                }
                catch (Exception e) { }
            }
        }
    }
}
